// main.cpp
#include <QApplication>
#include "VideoWidget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    VideoWidget w;
    w.show();
    return a.exec();
}

// VideoWidget.h
#ifndef VIDEOWIDGET_H
#define VIDEOWIDGET_H

#include <QWidget>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}

class VideoDecoderThread : public QThread {
    Q_OBJECT
public:
    VideoDecoderThread(const char* url, AVFrame* frame, QMutex* mutex, QWaitCondition* condition);
    ~VideoDecoderThread();
    void run();

private:
    const char* url;
    AVFrame* frame;
    QMutex* mutex;
    QWaitCondition* condition;
    AVFormatContext* formatContext = nullptr;
    AVCodecContext* codecContext = nullptr;
    SwsContext* swsContext = nullptr;
};

class VideoWidget : public QWidget {
    Q_OBJECT
public:
    VideoWidget(QWidget *parent = nullptr);
    ~VideoWidget();

private:
    QThread decoderThread;
    VideoDecoderThread* videoDecoder;
    QMutex mutex;
    QWaitCondition condition;
    AVFrame* frame;
    QImage image;
};

#endif // VIDEOWIDGET_H

// VideoWidget.cpp
#include "VideoWidget.h"

VideoDecoderThread::VideoDecoderThread(const char* url, AVFrame* frame, QMutex* mutex, QWaitCondition* condition)
    : url(url), frame(frame), mutex(mutex), condition(condition) {}

VideoDecoderThread::~VideoDecoderThread() {
    // 释放资源
    if (codecContext) {
        avcodec_close(codecContext);
    }
    if (formatContext) {
        avformat_close_input(&formatContext);
    }
    if (swsContext) {
        sws_freeContext(swsContext);
    }
}

void VideoDecoderThread::run() {
    // 初始化网络
    avformat_network_init();

    // 打开输入流
    if (avformat_open_input(&formatContext, url, nullptr, nullptr) < 0) {
        // 处理错误
        return;
    }

    // 寻找流信息
    if (avformat_find_stream_info(formatContext, nullptr) < 0) {
        // 处理错误
        return;
    }

    // 寻找视频流
    int videoStreamIndex = -1;
    for (unsigned int i = 0; i < formatContext->nb_streams; i++) {
        if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
            break;
        }
    }

    if (videoStreamIndex == -1) {
        // 处理错误
        return;
    }

    // 获取解码器
    AVCodec* codec = avcodec_find_decoder(formatContext->streams[videoStreamIndex]->codecpar->codec_id);
    if (!codec) {
        // 处理错误
        return;
    }

    // 创建解码器上下文
    codecContext = avcodec_alloc_context3(codec);
    avcodec_parameters_to_context(codecContext, formatContext->streams[videoStreamIndex]->codecpar);
    if (avcodec_open2(codecContext, codec, nullptr) < 0) {
        // 处理错误
        return;
    }

    // 初始化SWS
    swsContext = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt,
                                codecContext->width, codecContext->height, AV_PIX_FMT_RGB24,
                                SWS_BILINEAR, nullptr, nullptr, nullptr);

    AVPacket packet;
    while (true) {
        if (av_read_frame(formatContext, &packet) < 0) {
            // 处理错误
            break;
        }

        if (packet.stream_index == videoStreamIndex) {
            // 解码视频帧
            avcodec_send_packet(codecContext, &packet);
            while (avcodec_receive_frame(codecContext, frame) == 0) {
                mutex->lock();
                    // 转换格式
    uint8_t *data[4] = {nullptr};
    int linesize[4] = {0};
    av_image_alloc(data, linesize, codecContext->width, codecContext->height, AV_PIX_FMT_RGB24, 1);

    sws_scale(swsContext, frame->data, frame->linesize, 0, codecContext->height, data, linesize);

    // 更新图像
    image = QImage(data[0], codecContext->width, codecContext->height, QImage::Format_RGB888);

    // 通知主线程更新图像
    condition->wakeOne();
    mutex->unlock();

    av_freep(&data[0]);
    av_free(data);
        }

        av_packet_unref(&packet);
    }
}

VideoWidget::VideoWidget(QWidget *parent)
    : QWidget(parent), frame(av_frame_alloc()) {
    videoDecoder = new VideoDecoderThread("rtsp://your_rtsp_url", frame, &mutex, &condition);
    videoDecoder->start();
}

VideoWidget::~VideoWidget() {
    videoDecoder->requestInterruption();
    videoDecoder->wait();
    delete videoDecoder;
    av_frame_free(&frame);
}

void VideoWidget::paintEvent(QPaintEvent *event) {
    Q_UNUSED(event);
    mutex.lock();
    if (!image.isNull()) {
        QPainter painter(this);
        painter.drawImage(0, 0, image);
    }
    mutex.unlock();
}
